package org.dtrd.modules.control.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.dtrd.common.util.CheckUtil;
import org.dtrd.common.util.DateUtils;
import org.dtrd.config.system.Constant;
import org.dtrd.config.system.Constant.TargetProject;
import org.dtrd.modules.achievement.entity.bean.WeekRecordSummary;
import org.dtrd.modules.archive.entity.po.DtrdEntRdArchiveLaboratory;
import org.dtrd.modules.archive.entity.po.DtrdEntRdArchivePhysical;
import org.dtrd.modules.archive.service.IDtrdEntRdLaboratoryService;
import org.dtrd.modules.archive.service.IDtrdEntRdPhysicalService;
import org.dtrd.modules.control.entity.bean.PatientTargetValue;
import org.dtrd.modules.control.entity.bean.TargetAndDetailInfo;
import org.dtrd.modules.control.entity.bean.TargetTable;
import org.dtrd.modules.control.entity.po.DtrdEntRdSigninTarget;
import org.dtrd.modules.control.entity.po.DtrdEntRdSigninTargetDetail;
import org.dtrd.modules.control.entity.po.DtrdEntRdSigninTargetDetailDto;
import org.dtrd.modules.control.mapper.DtrdEntRdSigninTargetDetailMapper;
import org.dtrd.modules.control.service.IDtrdEntRdSigninTargetDetailService;
import org.dtrd.modules.control.service.IDtrdEntRdSigninTargetService;
import org.dtrd.modules.patient.entity.bean.report.*;
import org.dtrd.modules.patient.entity.po.DtrdEntRdReportTarget;
import org.dtrd.modules.patient.service.IDtrdEntRdReportTargetService;
import org.dtrd.modules.record.entity.bean.AvgRecordBean;
import org.dtrd.modules.record.entity.po.*;
import org.dtrd.modules.record.service.*;
import org.dtrd.modules.service.entity.po.DtrdRlPackagePatient;
import org.dtrd.modules.service.service.IDtrdRlPackagePatientService;
import org.dtrd.modules.util.NumberUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 *
 */
@Service
@DS("multi-datasource1")
@Slf4j
public class DtrdEntRdSigninTargetDetailServiceImpl extends ServiceImpl<DtrdEntRdSigninTargetDetailMapper, DtrdEntRdSigninTargetDetail> implements IDtrdEntRdSigninTargetDetailService {

    @Autowired
    private IDtrdEntRdSigninTargetService targetService;
    @Autowired
    private IBloodPressureRecordService bloodPressureRecordService;
    @Autowired
    private ISugarRecordService sugarRecordService;
    @Autowired
    private IHeightWeightRecordService heightWeightRecordService;
    @Autowired
    private IMedicalRecordService medicalRecordService;
    @Autowired
    private IWaistlineRecordService waistlineRecordService;
    @Autowired
    private IDtrdEntRdLaboratoryService laboratoryService;
    @Autowired
    private IDtrdEntRdUplowRecordService uplowRecordService;
    @Autowired
    private IDtrdEntRdSigninTargetService signinTargetService;
    @Autowired
    private IDtrdRlPackagePatientService packagePatientRlService;
    @Autowired
    private IDtrdEntRdPhysicalService physicalService;
    @Autowired
    private IDtrdEntRdReportTargetService reportTargetService;

    private final static String PLACEHOLDER = "--";


    @Override
    public List<DtrdEntRdSigninTargetDetail> getTargetDetailList(Integer targetId) {
        return baseMapper.getTargetDetailList(targetId);
    }

    @Override
    public boolean removeTargetDetails(Integer targetId) {
        LambdaQueryWrapper<DtrdEntRdSigninTargetDetail> wrapper = Wrappers.lambdaQuery(DtrdEntRdSigninTargetDetail.class)
                .eq(DtrdEntRdSigninTargetDetail::getTargetId, targetId);
        return remove(wrapper);
    }

    @Override
    public ReportTable getReportWeekTargets0(Integer patientId, String startDate, String endDate) {
        List<Integer> targetIds = targetService.getPatientTargetIds(patientId, startDate, endDate);
        log.info("DtrdEntRdSigninTargetDetailServiceImpl.getReportWeekTargets.[patientId, startDate, endDate] targetIds = " + targetIds);
        if (CollectionUtil.isNotEmpty(targetIds)) {
            // 创建表格对象
            ReportTable table = new ReportTable();
            // region表头
            List<ReportTableHeader> headers = new ArrayList<>(targetIds.size() + 1);
            // 第一列
            headers.add(new ReportTableHeader("打卡项/时间", "k0"));
            for (int i = 1; i <= targetIds.size(); i++) {
                headers.add(new ReportTableHeader("第" + i + "周", "k" + i));
            }
            table.setHeader(headers);
            // endregion
            // region表格数据
            List<Integer> targetTypes = Arrays.stream(Constant.TargetProject.values())
                    .map(Constant.TargetProject::getType)
                    .filter(t -> !t.equals(Constant.TargetProject.DRUG.getType()))
                    .collect(Collectors.toList());
            List<JSONObject> lineDate = new ArrayList<>(targetTypes.size());
            for (Integer targetType : targetTypes) {
                List<String> status = baseMapper.selectTargetStatusByType(targetType, patientId);
                JSONObject grid = new JSONObject();
                grid.set("k0", Constant.TargetProject.valueOf(targetType).getName());
                for (int i = 0; i < status.size(); i++) {
                    grid.set("k" + (i + 1), status.get(i));
                }
                lineDate.add(grid);
            }
            List<String> status = baseMapper.selectDrugStatus(Constant.TargetProject.DRUG.getType(), patientId);
            if (CollectionUtil.isNotEmpty(status) && isValidTargetStatusList(status)) {
                JSONObject grid = new JSONObject();
                grid.set("k0", Constant.TargetProject.DRUG.getName());
                for (int i = 0; i < status.size(); i++) {
                    grid.set("k" + (i + 1), status.get(i));
                }
                lineDate.add(grid);
            }
//            table.setData(lineDate);
            // endregion
            return table;
        }
        return null;
    }

    @Override
    public ReportTable getReportWeekTargets(Integer patientId, String startDate, String endDate) {
        List<Integer> targetIds = targetService.getPatientTargetIds(patientId, startDate, endDate);
        log.info("DtrdEntRdSigninTargetDetailServiceImpl.getReportWeekTargets.[patientId, startDate, endDate] targetIds = " + targetIds);
        if (CollectionUtil.isNotEmpty(targetIds)) {
            // 创建表格对象
            ReportTable table = new ReportTable();
            // region表头
            List<ReportTableHeader> headers = new ArrayList<>(targetIds.size() + 1);
            // 第一列
            headers.add(new ReportTableHeader("控制目标项", "k0"));
            headers.add(new ReportTableHeader("初始值", "k1"));
            // 每周达标率
            Map<Integer, Integer> map2 = getTargetIdToReachStandardRate(patientId, startDate, endDate);
            Map<String, String> scoreRecord = new HashMap<>(targetIds.size());
            Map<Integer, String> dateMap = new HashMap<>(targetIds.size());
            scoreRecord.put("k0", "达标率");
            for (int i = 0; i < targetIds.size(); i++) {
                Integer targetId = targetIds.get(i);
                int key = i + 2;
                headers.add(new ReportTableHeader("第" + (key-1) + "周", "k" + key));
                scoreRecord.put("k" + key, map2.get(targetId) + "%");
                dateMap.put(targetId, "k" + key);
            }
            table.setHeader(headers);
            // endregion
            // region表格数据
            List<DtrdEntRdSigninTargetDetailDto> detailList = baseMapper.selectTargetStatus(patientId, startDate, endDate);
            List<Map<String, String>> contentList = new ArrayList<>(targetIds.size());
            contentList.add(scoreRecord);
            Map<Integer, Map<String, String>> map = new HashMap<>(14);
            detailList.forEach(item -> {
                String key = dateMap.get(item.getTargetId());
                String keyValue = item.getContent();
                if (item.getProjectType() == TargetProject.DRUG.getType()) {
                    keyValue = item.getRemark();
                }
                groupByRecordType(map,  item.getProjectType(), TargetProject.valueOf(item.getProjectType()).getName(), key, keyValue, item);
            });
            log.info("DtrdEntRdSigninTargetDetailServiceImpl.getReportWeekTargets.[patientId, startDate, endDate] "+map);
            map.keySet().stream().sorted(Comparator.comparingInt(o -> o)).map(map::get).peek(recordMap -> dateMap.values().forEach(key -> {
                if (!recordMap.containsKey(key)) {
                    recordMap.put(key, "");
                }
            })).forEach(contentList::add);
            // 初始值
            Integer firstTargetId = detailList.get(0).getTargetId();
            List<DtrdEntRdSigninTargetDetailDto> firstTargetDetails = detailList.stream()
                    .filter(d -> Objects.equals(d.getTargetId(), firstTargetId))
                    .collect(Collectors.toList());
            for (Map<String, String> item : contentList) {
                String targetProjName = item.get("k0");
                String key = "k1";
                if (targetProjName.equals("达标率")) {
                    item.put(key, "/");
                }
                TargetProject project = TargetProject.valueOfName(targetProjName);
                if (project == null) {
                    continue;
                }
                Optional<DtrdEntRdSigninTargetDetailDto> optional = firstTargetDetails.stream()
                        .filter(d -> d.getProjectType() == project.getType())
                        .findAny();
                optional.ifPresent(o -> {
                    if (project.getType() != TargetProject.DRUG.getType()) {
                        item.put(key, o.getTargetLow().intValue()+"");
                    }else {
                        item.put(key, o.getRemark());
                    }
                });
            }
            table.setContent(contentList);
            // endregion
            return table;
        }
        return null;
    }

    @Override
    public ReportTable getReportWeekTargetsV2(Integer patientId) {
        // 获取用户的服务包的结束时间(选择只有已过期已退出的或者还是在服务的结束时间最末的)
        DtrdRlPackagePatient packagePatient = getEndTimePackage(patientId);
        if(packagePatient == null){
            return null;
        }
        // 添加时间范围
        Date startTime = packagePatient.getStartTime();
        Date endTime = packagePatient.getEndTime();
        Date nowTime = DateUtils.getDateYMD();
        // 选择最早结束的时间作为结束时间
        endTime = DateUtils.compareYMD(endTime, nowTime)?nowTime:endTime;
        List<List<String>> dateStringArray = DateUtils.getWeekStartEndStringArray(startTime, endTime);
        List<List<Date>> dateArray = DateUtils.getWeekStartEndDateArray(startTime, endTime);
        if(dateArray == null || dateStringArray == null){
            return null;
        }
        int weekSize = dateArray.size();
        // 创建表格对象
        ReportTable table = new ReportTable();
        // region表头
        List<ReportTableHeader> headers = new ArrayList<>(dateArray.size() + 2);
        // 创建表头
        headers.add(new ReportTableHeader("控制目标项", "k0"));
        headers.add(new ReportTableHeader("初始值", "k1"));
        for (int i = 0; i < weekSize; i++) {
//            Integer targetId = targetIds.get(i);
            int key = i + 2;
            headers.add(new ReportTableHeader("第" + (key-1) + "周", "k" + key));
        }
        table.setHeader(headers);
        // endregion 表头
        // region 获取每周的打卡目标值
        List<Map<Integer, DtrdEntRdSigninTargetDetail>> weekList = getWeekSigninTargetDetail(patientId, dateArray);
        // endregion 获取每周的打卡目标值
        List<Map<String, String>> content = new ArrayList<>();
        // region 添加达标率
        Map<String, String> reachRateMap = new HashMap<>();
        reachRateMap.put("k0", "达标率");
        reachRateMap.put("k1", "-");
        for(int i = 0; i < weekSize; i++){
            int key = i + 2;
            List<Date> date = dateArray.get(i);
            Integer weekReachRate = handlerReachRate(uplowRecordService.getPeriodControllerTargetsReachRate(
                    patientId,date.get(0),date.get(1),weekList.get(i)));
            reachRateMap.put("k"+key, weekReachRate +"%");
        }
        content.add(reachRateMap);
        // endregion 添加达标率
        for(Constant.TargetProject targetProject:Constant.TargetProject.values()){
            boolean isNotHave = true;
            // region 判断是否有这一项打卡计划，有则进行计算，没有直接跳过
            for(Map<Integer, DtrdEntRdSigninTargetDetail> item: weekList){
                if(item.containsKey(targetProject.getType())){
                    isNotHave = false;
                    break;
                }
            }
            if(isNotHave) {
                continue;
            }
            // endregion 判断是否有这一项打卡计划，有则进行计算，没有直接跳过
            Map<String, String> item = new HashMap<>();
            item.put("k0", targetProject.getName());
            // region 第14项用药情况需要单独处理
            if(targetProject.equals(TargetProject.DRUG)){
                item.put("k1", "-");
                for (int i = 0; i < weekSize; i++) {
                    Map<Integer, DtrdEntRdSigninTargetDetail> weekSigninTargetMap = weekList.get(i);
                    int key = i + 2;
                    DtrdEntRdSigninTargetDetail temp = weekSigninTargetMap.get(targetProject.getType());
                    String tempString = temp == null||temp.getRemark()==null?"-":temp.getRemark();
                    item.put("k"+key, tempString);
                }
                content.add(item);
                continue;
            }
            // endregion 第14项用药情况需要单独处理
            // region 获取初始值
            Float startValue = getFirstTargetValue(patientId, targetProject);
            item.put("k1", startValue == null ? "-":startValue.toString());
            // endregion 获取初始值

            // region 补充每周的打卡细节
            for(int i = 0; i<weekSize; i++){
                Map<Integer, DtrdEntRdSigninTargetDetail> weekSigninTargetMap = weekList.get(i);
                List<String> dateList = dateStringArray.get(i);
                int key = i + 2;
                // region 获取目标打卡值
                DtrdEntRdSigninTargetDetail temp = weekSigninTargetMap.get(targetProject.getType());
                Float avgValue = getAvgTargetValue(patientId, dateList.get(0), dateList.get(1), targetProject);
                String tempString = temp == null||temp.getValue()==null?"-":temp.getValue().toString();
                String avgValueString = avgValue == null? "-":avgValue.toString();
                item.put("k"+key, avgValueString + "/" + tempString);
                item.put("k"+key+"Target", tempString);
                item.put("k"+key+"Summary", avgValueString);
                // endregion 获取目标打卡值
            }
            // endregion 补充每周的打卡细节

            // 添加数据
            content.add(item);
        }
        table.setContent(content);
        return table;
    }

    /**
     * 计算周期内的平均达标率
     * @param reachRates
     * @return
     */
    private Integer handlerReachRate(Map<Date, Integer> reachRates){
        if(CollectionUtil.isEmpty(reachRates)){
            return 0;
        }
        int sum = 0;
        for(Integer i : reachRates.values()){
            sum += i;
        }
        return sum/reachRates.size();
    }

    /**
     * 获取每周的打卡目标项
     * @param patientId
     * @param dateArray 里面保存的需为两个datetime的列表，date(0)代表起始时间，date(1)代表结束时间
     * @return
     */
    @Override
    public List<Map<Integer, DtrdEntRdSigninTargetDetail>> getWeekSigninTargetDetail(Integer patientId, List<List<Date>> dateArray){
        List<Map<Integer, DtrdEntRdSigninTargetDetail>> result = new ArrayList<>(dateArray.size());
        LambdaQueryWrapper<DtrdEntRdSigninTarget> wrapper = null;
        LambdaQueryWrapper<DtrdEntRdSigninTargetDetail> wrapper1 = null;
        for(int i =0; i<dateArray.size(); i++){
            List<Date> item = dateArray.get(i);
            Map<Integer, DtrdEntRdSigninTargetDetail> signinTargetDetailMap = new HashMap<>();
            wrapper = Wrappers.lambdaQuery(DtrdEntRdSigninTarget.class)
                    .eq(DtrdEntRdSigninTarget::getIsDel, 0)
                    .eq(DtrdEntRdSigninTarget::getPatientId, patientId)
                    .le(DtrdEntRdSigninTarget::getCreateTime,item.get(1))
                    .orderByDesc(DtrdEntRdSigninTarget::getCreateTime)
                    .last("limit 1");
            DtrdEntRdSigninTarget signinTarget = signinTargetService.getOne(wrapper);
            if(signinTarget == null){
                result.add(i , signinTargetDetailMap);
                continue;
            }
            wrapper1 = Wrappers.lambdaQuery(DtrdEntRdSigninTargetDetail.class)
                    .eq(DtrdEntRdSigninTargetDetail::getIsDel, 0)
                    .eq(DtrdEntRdSigninTargetDetail::getTargetId, signinTarget.getDataId())
                    .eq(DtrdEntRdSigninTargetDetail::getPatientId, patientId);
            List<DtrdEntRdSigninTargetDetail> signinTargetDetailsList = list(wrapper1);

            if(CollectionUtil.isNotEmpty(signinTargetDetailsList)){
                signinTargetDetailMap = signinTargetDetailsList.stream().collect(
                        Collectors.toMap(DtrdEntRdSigninTargetDetail::getProjectType,
                                Function.identity(),
                                (key1, key2) -> key2));
            }
            result.add(i , signinTargetDetailMap);
        }
        return result;
    }

    private DtrdRlPackagePatient getEndTimePackage(Integer patientId) {
        // 获取用户的服务包的结束时间(选择只有已退出的已到期或者还是在服务的结束时间最末的)，选择已到期或者在服务将 (1,3,5)->(1,5)
        LambdaQueryWrapper<DtrdRlPackagePatient> packagePatientWrapper = Wrappers.lambdaQuery(DtrdRlPackagePatient.class)
                .eq(DtrdRlPackagePatient::getIsDel, 0)
                .eq(DtrdRlPackagePatient::getPatientId, patientId)
                .in(DtrdRlPackagePatient::getStatus,1,3,5)
                .orderByDesc(DtrdRlPackagePatient::getEndTime)
                .last("limit 1");
        return packagePatientRlService.getOne(packagePatientWrapper);
    }

    @Override
    public List<ControllerTargetReport> getPeriodReportTarget(Integer patientId, String startDate, String endDate,
                                                              String lastStartDate, String lastEndDate, boolean flag, Constant.ReportType reportType) {
        DtrdEntRdSigninTarget dtrdEntRdSigninTarget = signinTargetService.getPatientLastTargetId(patientId, endDate);
        if(dtrdEntRdSigninTarget == null){
//            没有打卡目标，直接就返回空
            return null;
        }
        LambdaQueryWrapper<DtrdEntRdSigninTargetDetail> wrapper = Wrappers.lambdaQuery(DtrdEntRdSigninTargetDetail.class)
                .eq(DtrdEntRdSigninTargetDetail::getIsDel, 0)
                .eq(DtrdEntRdSigninTargetDetail::getTargetId, dtrdEntRdSigninTarget.getDataId())
                .eq(DtrdEntRdSigninTargetDetail::getPatientId, patientId);
        List<DtrdEntRdSigninTargetDetail> list = list(wrapper);
        if(CollectionUtil.isNotEmpty(list)){
            List<ControllerTargetReport> targetReportsList = new ArrayList<>(list.size());
            for(DtrdEntRdSigninTargetDetail temp: list){
//                对周报的控制目标实验室检查这部分进行过滤
                if((reportType == Constant.ReportType.REPORT_WEEK)&&isFilterControllerTarget(temp.getProjectType())){
                    continue;
                }
                ControllerTargetReport targetReport = new ControllerTargetReport();
                Constant.TargetProject targetProject = Constant.TargetProject.valueOf(temp.getProjectType());
//              region 设置所有的取值
                targetReport.setTypeId(temp.getProjectType());
                targetReport.setTypeName(targetProject.getName());
                targetReport.setStartValue(getFirstTargetValue(patientId, targetProject));
                Float value = getAvgTargetValue(patientId, startDate, endDate, targetProject);
                targetReport.setThisPeriodValue(value);
                if(flag){
                    Float lastValue = getAvgTargetValue(patientId, lastStartDate, lastEndDate, targetProject);
                    targetReport.setLastPeriodValue(lastValue);
                    targetReport = computeTargetReport(targetReport, value, lastValue);
                }
                targetReport.setControllerValue(temp.getValue());
                targetReport.setReferenceValue(targetProject.getReferenceValue());
//              endregion 设置所有的取值
//                ControllerTargetReport targetReport = getTargetReportParseFromPo(temp, patientId, startDate, endDate,lastStartDate,lastEndDate,flag);
                targetReportsList.add(targetReport);
            }
            return targetReportsList;
        }
        return null;
    }

    @Override
    public List<ControllerTargetReport> getSummaryReportTarget(Integer patientId, String startDate, String endDate) {
        DtrdEntRdSigninTarget dtrdEntRdSigninTarget = signinTargetService.getPatientLastTargetId(patientId, endDate);
        if(dtrdEntRdSigninTarget == null){
//            没有打卡目标，直接就返回空
            return null;
        }
        LambdaQueryWrapper<DtrdEntRdSigninTargetDetail> wrapper = Wrappers.lambdaQuery(DtrdEntRdSigninTargetDetail.class)
                .eq(DtrdEntRdSigninTargetDetail::getIsDel, 0)
                .eq(DtrdEntRdSigninTargetDetail::getTargetId, dtrdEntRdSigninTarget.getDataId())
                .eq(DtrdEntRdSigninTargetDetail::getPatientId, patientId);
        List<DtrdEntRdSigninTargetDetail> list = list(wrapper);
        if(CollectionUtil.isNotEmpty(list)){
            List<ControllerTargetReport> targetReportsList = new ArrayList<>(list.size());
            for(DtrdEntRdSigninTargetDetail temp: list){
                Constant.TargetProject targetProject = Constant.TargetProject.valueOf(temp.getProjectType());
                ControllerTargetReport targetReport = new ControllerTargetReport();
                targetReport.setTypeId(temp.getProjectType());
                targetReport.setTypeName(targetProject.getName());
                Float startValue = getFirstTargetValue(patientId, targetProject);
                targetReport.setStartValue(startValue);
                Float thisPeriodValue = getAvgTargetValue(patientId, startDate, endDate, targetProject);
                if(startValue != null && thisPeriodValue != null){
                    targetReport.setThisPeriodValue(thisPeriodValue);
                    Float trendValue = (float)Math.round((startValue - thisPeriodValue)*100)/100;
                    targetReport.setTrendValue(trendValue);
                    if(trendValue == 0){
                        targetReport.setTrend(2);
                    }else {
                        targetReport.setTrend(trendValue>0?1:3);
                    }
                }
                targetReport.setControllerValue(temp.getValue());
                targetReport.setReferenceValue(targetProject.getReferenceValue());
                targetReportsList.add(targetReport);
            }
            return targetReportsList;
        }
        return null;
    }

    /**
     * 过滤控制目标的实验室检查
     * @param projectType
     * @return
     */
    private boolean isFilterControllerTarget(Integer projectType){
        boolean flag = false;
        Constant.TargetProject targetProject = Constant.TargetProject.valueOf(projectType);
        switch (targetProject){
            case HBA1C:// "糖化血红蛋白"
            case TC://"总胆固醇(mmol/L)"),
            case TG://"甘油三酯(mmol/L)"),
            case LDL://"低密度脂蛋白(mmol/L)"
            case HDL://"高密度脂蛋白(mmol/L)"
            case ALT://"谷丙转氨酶(mmol/L)"),
            case BIL://"总胆红素(mmol/L)"),
            case AST://"谷草转氨酶(mmol/L)"),
            case ALP://"碱性磷酸酶(mmol/L)"),
            case UAE://"尿微量白蛋白(mmol/L)"),
            case UAE_24H://"24h尿白蛋白(mmol/L)"),
            case ACR://"尿白蛋白/尿肌酐(mmol/L)"),
            case Cr://"血清肌酐(mmol/L)"),
            case UREANITROGEN://"尿素氮(mmol/L)"),
            case GFR://"肾小球滤过率(mmol/L)"),
            case CrCl://"内生肌酐清除率(mmol/L)"),
            case BUA:
                flag = true;
                break;//"血尿酸(mmol/L)"
            default:
        }
        return flag;
    }

    /**
     *
     * @param signinTargetDetail
     * @param patientId
     * @param startDate
     * @param endDate
     * @param lastStartDate
     * @param lastEndDate
     * @param flag
     * @return
     * @deprecated 该方法已弃用，使用for循环封装接口（已经将初始值与平均值的方法单独封装） qiannai 2022、9、18
     */
    private ControllerTargetReport getTargetReportParseFromPo(DtrdEntRdSigninTargetDetail signinTargetDetail, Integer patientId, String startDate, String endDate,String lastStartDate, String lastEndDate, boolean flag){
        // 根据控制项，获取对应控制项周期内的检查平均
        ControllerTargetReport targetReport = new ControllerTargetReport();
        Constant.TargetProject targetProjectConstant = Constant.TargetProject.valueOf(signinTargetDetail.getProjectType());
        Float controllerValue = signinTargetDetail.getValue();
        Float value;
        Float lastValue;
        assert targetProjectConstant!=null;
        targetReport.setTypeId(signinTargetDetail.getProjectType());
        targetReport.setTypeName(targetProjectConstant.getName());
        targetReport.setControllerValue(controllerValue);
        switch (targetProjectConstant){
            case BMI:
                // 完成
                value = getAvgTargetValue(patientId, startDate, endDate, TargetProject.BMI);
                if(flag){
                    lastValue = getAvgTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.BMI);
                    targetReport.setLastPeriodValue(lastValue);
                    targetReport = computeTargetReport(targetReport, value, lastValue);
                }
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.BMI));
                targetReport.setReferenceValue("18.5~23.9");
                break;//BMI
            case WEIGHT:
                //完成
                value = getAvgTargetValue(patientId, startDate, endDate, TargetProject.WEIGHT);
                if(flag){
                    lastValue = getAvgTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.WEIGHT);
                    targetReport.setLastPeriodValue(lastValue);
                    targetReport = computeTargetReport(targetReport, value, lastValue);
                }
                targetReport.setStartValue(getFirstTargetValue(patientId, TargetProject.WEIGHT));
                targetReport.setReferenceValue("65.0");
                break;// 体重(kg)
            case WAIST:
                // 计算腰围平均值
                value = getAvgTargetValue(patientId, startDate, endDate, TargetProject.WAIST);
                if(flag){
                    lastValue = getAvgTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.WAIST);
                    targetReport.setLastPeriodValue(lastValue);
                    targetReport = computeTargetReport(targetReport, value, lastValue);
                }
                targetReport.setStartValue(getFirstTargetValue(patientId, TargetProject.WAIST));
                targetReport.setReferenceValue("<90.0");
                break;// 腰围(cm)
            case HBA1C:
                // 完成 实验室检查数值改为输入
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.HBA1C);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.HBA1C));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, Constant.TargetProject.HBA1C));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.HBA1C.getReferenceValue());
                break;// 糖化血红蛋白(%)
            case FBG:
                // 完成
                value = getAvgTargetValue(patientId, startDate, endDate, TargetProject.FBG);
                if(flag){
                    lastValue = getAvgTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.FBG);
                    targetReport.setLastPeriodValue(lastValue);
                    targetReport = computeTargetReport(targetReport, value, lastValue);
                }
                targetReport.setStartValue(getFirstTargetValue(patientId, TargetProject.FBG));
                targetReport.setReferenceValue("6.0~8.0");
                break;// "空腹血糖(mmol/L)
            case PBG:
                // 完成
                value = getAvgTargetValue(patientId, startDate, endDate, TargetProject.PBG);
                if(flag){
                    lastValue = getAvgTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.PBG);
                    targetReport.setLastPeriodValue(lastValue);
                    targetReport = computeTargetReport(targetReport, value, lastValue);
                }
                targetReport.setStartValue(getFirstTargetValue(patientId, TargetProject.PBG));
                targetReport.setReferenceValue("6.0~8.0");
                break;// "餐后血糖(mmol/L)")
            case PRESSURE_LOW:
                // 已完成
                value = getAvgTargetValue(patientId, startDate, endDate, TargetProject.PRESSURE_LOW);
                if(flag){
                    lastValue = getAvgTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.PRESSURE_LOW);
                    targetReport.setLastPeriodValue(lastValue);
                    targetReport = computeTargetReport(targetReport, value, lastValue);
                }
                targetReport.setStartValue(getFirstTargetValue(patientId, TargetProject.PRESSURE_LOW));
                targetReport.setReferenceValue("<80.0");
                break;//"舒张压/低压 mmHg",
            case PRESSURE_HIGH:
                value = getAvgTargetValue(patientId, startDate, endDate, TargetProject.PRESSURE_HIGH);
                if(flag){
                    lastValue = getAvgTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.PRESSURE_HIGH);
                    targetReport.setLastPeriodValue(lastValue);
                    targetReport = computeTargetReport(targetReport, value, lastValue);
                }
                targetReport.setStartValue(getFirstTargetValue(patientId, TargetProject.PRESSURE_HIGH));
                targetReport.setReferenceValue("<140.0");
                break;//"收缩压/高压 mmHg",
            case HEART_RATE:
                // 已完成
                value = getAvgTargetValue(patientId, startDate, endDate, TargetProject.HEART_RATE);
                if(flag){
                    lastValue = getAvgTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.HEART_RATE);
                    targetReport.setLastPeriodValue(lastValue);
                    targetReport = computeTargetReport(targetReport, value, lastValue);
                }
                targetReport.setStartValue(getFirstTargetValue(patientId, TargetProject.HEART_RATE));
                targetReport.setReferenceValue("60~100");
                break;//"心率/脉搏(次/分钟)"
            case TC:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.TC);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.TC));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, Constant.TargetProject.TC));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.TC.getReferenceValue());
                break;//"总胆固醇(mmol/L)"),
            case TG:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.TG);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.TG));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, Constant.TargetProject.TG));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.TG.getReferenceValue());
                break;//"甘油三酯(mmol/L)"),
            case LDL:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.LDL_C);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.LDL));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.LDL));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.LDL_C.getReferenceValue());
                break;//"低密度脂蛋白(mmol/L)"
            case HDL:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.HDL_C);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.HDL));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.HDL));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.HDL_C.getReferenceValue());
                break;//"高密度脂蛋白(mmol/L)"
            case ALT:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.ALT);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.ALT));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.ALT));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.ALT.getReferenceValue());
                break;//"谷丙转氨酶(mmol/L)"),
            case BIL:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.TBIL);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.BIL));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, Constant.TargetProject.BIL));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.TBIL.getReferenceValue());
                break;//"总胆红素(mmol/L)"),
            case AST:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.AST);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.AST));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.AST));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.AST.getReferenceValue());
                break;//"谷草转氨酶(mmol/L)"),
            case ALP:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.ALP);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.ALP));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.ALP));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.ALP.getReferenceValue());
                break;//"碱性磷酸酶(mmol/L)"),
            case UAE:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.UAE);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.UAE));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.UAE));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.UAE.getReferenceValue());
                break;//"尿微量白蛋白(mmol/L)"),
            case UAE_24H:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.UAE24);
                targetReport.setStartValue(getFirstTargetValue(patientId, TargetProject.UAE_24H));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.UAE_24H));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.UAE24.getReferenceValue());
                break;//"24h尿白蛋白(mmol/L)"),
            case ACR:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.ACR);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.ACR));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.ACR));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.ACR.getReferenceValue());
                break;//"尿白蛋白/尿肌酐(mmol/L)"),
            case Cr:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.CR);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.Cr));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.Cr));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.CR.getReferenceValue());
                break;//"血清肌酐(mmol/L)"),
            case UREANITROGEN:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.UREA_NITROGEN);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.UREANITROGEN));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.UREANITROGEN));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.UREA_NITROGEN.getReferenceValue());
                break;//"尿素氮(mmol/L)"),
            case GFR:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.GFR);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.GFR));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.GFR));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.GFR.getReferenceValue());
                break;//"肾小球滤过率(mmol/L)"),
            case CrCl:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.CREATININE_RATE);
                targetReport.setStartValue(getFirstTargetValue(patientId, Constant.TargetProject.CrCl));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.CrCl));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.CREATININE_RATE.getReferenceValue());
                break;//"内生肌酐清除率(mmol/L)"),
            case BUA:
//                targetReport = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate,targetReport,controllerValue, Constant.LABORATORY.BUA);
                targetReport.setStartValue(getFirstTargetValue(patientId, TargetProject.BUA));
                if(flag){
                    targetReport.setLastPeriodValue(getReportTargetValue(patientId, lastStartDate, lastEndDate, TargetProject.BUA));
                }
                targetReport.setReferenceValue(Constant.LABORATORY.BUA.getReferenceValue());
                break;//"血尿酸(mmol/L)"
            default:
                targetReport.setReferenceValue("该对象还没进行枚举，请进行补充");
        }
        return targetReport;
    }

    /***
     * 获取实验室检查上月输入的数值
     * @param patientId
     * @param lastStartDate
     * @param lastEndDate
     * @param targetProject
     * @return
     */
    private Float getReportTargetValue(Integer patientId, String lastStartDate, String lastEndDate, TargetProject targetProject) {
        LambdaQueryWrapper<DtrdEntRdReportTarget> queryWrapper = Wrappers.lambdaQuery(DtrdEntRdReportTarget.class)
                .eq(DtrdEntRdReportTarget::getIsDel, 0)
                .eq(DtrdEntRdReportTarget::getPatientId, patientId)
                .eq(DtrdEntRdReportTarget::getTypeId, targetProject.getType())
                .orderByDesc(DtrdEntRdReportTarget::getRecordDate)
                .ge(DtrdEntRdReportTarget::getRecordDate, lastStartDate)
                .le(DtrdEntRdReportTarget::getRecordDate, lastEndDate)
                .last("limit 1");
        DtrdEntRdReportTarget reportTarget = reportTargetService.getOne(queryWrapper);
        return reportTarget != null? reportTarget.getRecordValue():null;
    }

    /**
     * 封装计算方法
     * @param report ControllerTargetReport对象
     * @param value 计算出来的周期平均值
     * @param controllerValue 控制目标值
     * @return
     */
    private ControllerTargetReport computeTargetReport(ControllerTargetReport report, Float value, Float controllerValue){
        Float trendValue = null;
        if(value != null){
            report.setThisPeriodValue(value);
            if(controllerValue == null){
                return report;
            }
            trendValue = (float)Math.round((value - controllerValue)*100)/100;
            report.setTrendValue(trendValue);
            if(trendValue == 0){
                report.setTrend(2);
            }else {
                report.setTrend(trendValue>0?1:3);
            }
        }
        return report;
    }

    private DtrdEntRdArchivePhysical getArchivePhysical(Integer patientId){
        LambdaQueryWrapper<DtrdEntRdArchivePhysical> queryWrapper = Wrappers.lambdaQuery(DtrdEntRdArchivePhysical.class)
                .eq(DtrdEntRdArchivePhysical::getIsDel, 0)
                .orderByDesc(DtrdEntRdArchivePhysical::getCreateTime)
                .eq(DtrdEntRdArchivePhysical::getPatientId, patientId)
                .last("limit 1");
        return physicalService.getOne(queryWrapper);
    }

    @Override
    public Float getFirstTargetValue(Integer patientId, Constant.TargetProject targetProject){
        Float value = null;
        DtrdEntRdArchivePhysical archivePhysical = null;
        switch (targetProject){
            case BMI:
                value = heightWeightRecordService.getFirstHeightWeightRecord(patientId, Constant.HEIGHT_WEIGHT.BMI);
                if(value == null){
                    archivePhysical = getArchivePhysical(patientId);
                    if(archivePhysical != null){
                        value = archivePhysical.getBmi();
                    }
                }
                break;//BMI
            case WEIGHT:
                value = heightWeightRecordService.getFirstHeightWeightRecord(patientId, Constant.HEIGHT_WEIGHT.WEIGHT);
                if(value == null){
                    archivePhysical = getArchivePhysical(patientId);
                    if(archivePhysical != null){
                        value = archivePhysical.getWeight();
                    }
                }
                break;// 体重(kg)
            case WAIST:
                value = waistlineRecordService.getFirstWaistlineValue(patientId);
                if(value != null){
                    break;
                }
                archivePhysical = getArchivePhysical(patientId);
                if(archivePhysical != null){
                    value = archivePhysical.getWaist();
                }
                break;// 腰围(cm)
            case HBA1C:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.HBA1C);
                break;// 糖化血红蛋白(%)
            case FBG:
                value = laboratoryService.getFirstLaboratoryValue(patientId,Constant.LABORATORY.FBG);
                break;// "空腹血糖(mmol/L)
            case PBG:
                value = laboratoryService.getFirstLaboratoryValue(patientId,Constant.LABORATORY.PBG);
                break;// "餐后血糖(mmol/L)")
            case PRESSURE_LOW:
                value = bloodPressureRecordService.getFirstBloodPressureValue(patientId, Constant.BloodPressure.PRESSURE_LOW);
                if(value!=null){
                    break;
                }
                archivePhysical = getArchivePhysical(patientId);
                if(archivePhysical != null){
                    value = archivePhysical.getBloodDiastolicPress();
                }
                break;//"舒张压/低压 mmHg",
            case PRESSURE_HIGH:
                value = bloodPressureRecordService.getFirstBloodPressureValue(patientId, Constant.BloodPressure.PRESSURE_HIGH);
                if(value != null){
                    break;
                }
                archivePhysical = getArchivePhysical(patientId);
                if(archivePhysical != null){
                    value = archivePhysical.getBloodSystolicPress();
                }
                break;//"收缩压/高压 mmHg",
            case HEART_RATE:
                value = bloodPressureRecordService.getFirstBloodPressureValue(patientId, Constant.BloodPressure.HEART_RATE);
                if(value !=null){
                    break;
                }
                archivePhysical = getArchivePhysical(patientId);
                if(archivePhysical != null){
                    value = archivePhysical.getHeartRate();
                }
                break;//"心率/脉搏(次/分钟)"
            case TC:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.TC);
                break;//"总胆固醇(mmol/L)"),
            case TG:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.TG);
                break;//"甘油三酯(mmol/L)"),
            case LDL:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.LDL_C);
                break;//"低密度脂蛋白(mmol/L)"
            case HDL:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.HDL_C);
                break;//"高密度脂蛋白(mmol/L)"
            case ALT:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.ALT);
                break;//"谷丙转氨酶(mmol/L)"),
            case BIL:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.TBIL);
                break;//"总胆红素(mmol/L)"),
            case AST:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.AST);
                break;//"谷草转氨酶(mmol/L)"),
            case ALP:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.ALP);
                break;//"碱性磷酸酶(mmol/L)"),
            case UAE:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.UAE);
                break;//"尿微量白蛋白(mmol/L)"),
            case UAE_24H:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.UAE24);
                break;//"24h尿白蛋白(mmol/L)"),
            case ACR:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.ACR);
                break;//"尿白蛋白/尿肌酐(mmol/L)"),
            case Cr:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.CR);
                break;//"血清肌酐(mmol/L)"),
            case UREANITROGEN:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.UREA_NITROGEN);
                break;//"尿素氮(mmol/L)"),
            case GFR:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.GFR);
                break;//"肾小球滤过率(mmol/L)"),
            case CrCl:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.CREATININE_RATE);
                break;//"内生肌酐清除率(mmol/L)"),
            case BUA:
                value = laboratoryService.getFirstLaboratoryValue(patientId, Constant.LABORATORY.BUA);
                break;//"血尿酸(mmol/L)"
            default:
        }
        return value;
    }

    @Override
    public Float getAvgTargetValue(Integer patientId, String startDate, String endDate, TargetProject targetProject) {
        Float value = null;
        switch (targetProject){
            case BMI:
                // 完成
                Integer bmi = heightWeightRecordService.getAvgBmi(patientId, startDate, endDate);
                if (bmi != null){
                    value = new Float(bmi);
                }
                break;//BMI
            case WEIGHT:
                //完成
                value =  heightWeightRecordService.getAvgWeight(patientId, startDate, endDate);
                break;// 体重(kg)
            case WAIST:
                // 计算腰围平均值
                AvgRecordBean waistRecord = waistlineRecordService.getAvgValue(patientId, startDate, endDate);
                if (waistRecord != null && waistRecord.getAvgValue() != null) {
                    value = waistRecord.getAvgValue();
                }
                break;// 腰围(cm)
            case FBG:
                // 完成
                String beforeBreakfastType = "(" + Constant.SugarRecordType.BEFOREBREAKFAST.getType() + ")";
                // 计算本周空腹平均血糖
                value = sugarRecordService.getAvgSugarRecord(patientId, startDate, endDate, beforeBreakfastType);
                break;// "空腹血糖(mmol/L)
            case PBG:
                // 完成
                // 计算餐后血糖
                String afterType = "(" + Constant.SugarRecordType.AFTERBREAKFAST.getType() + "," + Constant.SugarRecordType.AFTERLUNCH.getType() + "," + Constant.SugarRecordType.AFTERDINNER.getType() + ")";
                // 计算本周餐后
                value = sugarRecordService.getAvgSugarRecord(patientId, startDate, endDate, afterType);
                break;// "餐后血糖(mmol/L)")
            case PRESSURE_LOW:
                // 已完成
                Integer bpLowAvgValue = bloodPressureRecordService.getAvgBloodLowPressure(patientId, startDate, endDate);
                if(bpLowAvgValue != null){
                    value = new Float(bpLowAvgValue);
                }
                break;//"舒张压/低压 mmHg",
            case PRESSURE_HIGH:
                // 已完成
                // 本周高压
                Integer bpHighAvgValue = bloodPressureRecordService.getAvgBloodHighPressure(patientId, startDate, endDate);
                if(bpHighAvgValue != null){
                    value = new Float(bpHighAvgValue);
                }
                break;//"收缩压/高压 mmHg",
            case HEART_RATE:
                // 已完成
                Integer heartLowAvgValue = bloodPressureRecordService.getAvgBloodHeartrate(patientId, startDate, endDate);
                if(heartLowAvgValue != null){
                    value = new Float(heartLowAvgValue);
                }
                break;//"心率/脉搏(次/分钟)"
            case HBA1C:
                // 完成
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.HBA1C);
//                break;// 糖化血红蛋白(%)
            case TC:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.TC);
//                break;//"总胆固醇(mmol/L)"),
            case TG:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.TG);
//                break;//"甘油三酯(mmol/L)"),
            case LDL:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.LDL_C);
//                break;//"低密度脂蛋白(mmol/L)"
            case HDL:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.HDL_C);
//                break;//"高密度脂蛋白(mmol/L)"
            case ALT:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.ALT);
//                break;//"谷丙转氨酶(mmol/L)"),
            case BIL:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.TBIL);
//                break;//"总胆红素(mmol/L)"),
            case AST:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.AST);
//                break;//"谷草转氨酶(mmol/L)"),
            case ALP:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.ALP);
//                break;//"碱性磷酸酶(mmol/L)"),
            case UAE:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.UAE);
//                break;//"尿微量白蛋白(mmol/L)"),
            case UAE_24H:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.UAE24);
//                break;//"24h尿白蛋白(mmol/L)"),
            case ACR:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.ACR);
//                break;//"尿白蛋白/尿肌酐(mmol/L)"),
            case Cr:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.CR);
//                break;//"血清肌酐(mmol/L)"),
            case UREANITROGEN:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.UREA_NITROGEN);
//                break;//"尿素氮(mmol/L)"),
            case GFR:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.GFR);
//                break;//"肾小球滤过率(mmol/L)"),
            case CrCl:
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.CREATININE_RATE);
//                break;//"内生肌酐清除率(mmol/L)"),
            case BUA:
                value = getReportTargetValue(patientId, startDate, endDate, targetProject);
                break;
//                value = laboratoryService.getAvgLaboratoryType(patientId, startDate, endDate, Constant.LABORATORY.BUA);
//                break;//"血尿酸(mmol/L)"
            default:
        }
        return value;
    }

    private void groupByRecordType(Map<Integer, Map<String, String>> map, Integer mapIndex, String signinName, String key, String keyValue, DtrdEntRdSigninTargetDetailDto item) {
        Map<String, String> tmp = map.get(mapIndex);
        if (tmp == null) {
            tmp = new HashMap<>(8);
        }
        tmp.put("k0", signinName);
        if (keyValue != null) {
            tmp.put(key, keyValue);
        }
        if (item != null) {
            tmp.put(key + "State", "" + item.getRecordStatus());
            tmp.put(key + "Target", "" + item.getTargetLow());
            tmp.put(key + "Summary", "" + item.getWeekSummary());
        }
        map.put(mapIndex, tmp);
    }

    @Override
    public boolean saveTargetDetailRealValue(Integer targetId, Float value, Integer projectType) {
        return baseMapper.updateTargetDetailRealValue(targetId, value, projectType);
    }

    @Override
    public Map<Integer, Integer> getTargetIdToReachStandardRate(Integer patientId, String startDate, String endDate) {
        List<DtrdEntRdSigninTargetDetail> targetDetails =  baseMapper.selectTargetDetailsByType(patientId, startDate, endDate);
        Map<Integer, List<DtrdEntRdSigninTargetDetail>> map = targetDetails.stream()
                .collect(Collectors.groupingBy(DtrdEntRdSigninTargetDetail::getTargetId));
        if (MapUtil.isNotEmpty(map)) {
            HashMap<Integer, Integer> result = new HashMap<>();
            for (Map.Entry<Integer, List<DtrdEntRdSigninTargetDetail>> entry : map.entrySet()) {
                List<DtrdEntRdSigninTargetDetail> value = entry.getValue();
                long reachStandardCount = value.stream()
                        // 当前值小于等于控制目标则控制目标达标
                        .filter(v -> {
                            if (v.getProjectType() != null && v.getValue() != null && v.getTargetHigh() != null) {
                                return v.getProjectType() != TargetProject.DRUG.getType() && v.getValue() <= v.getTargetHigh();
                            }else {
                                return false;
                            }
                        })
                        .count();
                result.put(entry.getKey(), (int) (reachStandardCount * 100 / value.size()));
            }
            return result;
        }
        return null;
    }

    /**
     * 如果不是全部都是 "" 的列表就是有效的
     */
    private boolean isValidTargetStatusList(List<String> targets) {
        return targets.stream().anyMatch(CheckUtil::isNotEmpty);
    }

    @Override
    public List<ReportTargetBean> getReportFirstTargets(Integer patientId) {
        Integer targetId = targetService.getPatientFirstTargetId(patientId);
        if (targetId == null) {
            return null;
        }
        LambdaQueryWrapper<DtrdEntRdSigninTargetDetail> wrapper = Wrappers.lambdaQuery(DtrdEntRdSigninTargetDetail.class)
                .eq(DtrdEntRdSigninTargetDetail::getTargetId, targetId)
                .orderByAsc(DtrdEntRdSigninTargetDetail::getProjectType);
        List<DtrdEntRdSigninTargetDetail> targetDetails = list(wrapper);
        if (CollectionUtil.isNotEmpty(targetDetails)) {
            List<ReportTargetBean> list = new ArrayList<>(targetDetails.size());
            for (DtrdEntRdSigninTargetDetail detail : targetDetails) {
                list.add(ReportTargetBean.buildFirstReportTarget(detail));
            }
            return list;
        }
        return null;
    }

    @Override
    public PatientTargetValue getPatientHomePageInfo(Integer patientId) {
        DtrdEntRdSigninTarget target = targetService.getOne(Wrappers.lambdaQuery(DtrdEntRdSigninTarget.class)
                .eq(DtrdEntRdSigninTarget::getPatientId, patientId)
                .eq(DtrdEntRdSigninTarget::getCurrentStatus, Constant.TargetStatus.USING.getType()));
        if (target == null) {
            return null;
        }
        List<DtrdEntRdSigninTargetDetail> targetDetails = list(Wrappers.lambdaQuery(DtrdEntRdSigninTargetDetail.class)
                .eq(DtrdEntRdSigninTargetDetail::getTargetId, target.getDataId())
                .eq(DtrdEntRdSigninTargetDetail::getPatientId, patientId));
        PatientTargetValue homePageTarget = new PatientTargetValue();
        return homePageTarget.parseFromPo(targetDetails);
    }

    private final static Integer thisWeek = 1;

    private final static Integer lastWeek = 2;

    @Override
    public PatientTargetValue getPatientTargetRealValue(Integer patientId, Integer type) {
        PatientTargetValue patientTargetValue = new PatientTargetValue();
        List<Date> thisWeekDays = DateUtils.getWeekDate(new Date());
        List<Date> lastWeekDays = DateUtils.getWeekDate(DateUtil.offset(thisWeekDays.get(0), DateField.DAY_OF_MONTH, -1));
        // 血压 & 心率
        LambdaQueryWrapper<DtrdEntRdSigninBloodPressure> queryWrapper1 = Wrappers.lambdaQuery(DtrdEntRdSigninBloodPressure.class)
                .eq(DtrdEntRdSigninBloodPressure::getPatientId, patientId);
        if (Objects.equals(type, thisWeek)) {
            queryWrapper1.le(DtrdEntRdSigninBloodPressure::getRecordDate, thisWeekDays.get(6))
                    .ge(DtrdEntRdSigninBloodPressure::getRecordDate, thisWeekDays.get(0));
        }
        if (Objects.equals(type, lastWeek)) {
            queryWrapper1.le(DtrdEntRdSigninBloodPressure::getRecordDate, lastWeekDays.get(6))
                    .ge(DtrdEntRdSigninBloodPressure::getRecordDate, lastWeekDays.get(0));
        }
        List<DtrdEntRdSigninBloodPressure> bloodPressures = bloodPressureRecordService.list(queryWrapper1);
        if (CollectionUtil.isNotEmpty(bloodPressures)) {
            // 高压
            Double avgHigh = bloodPressures.stream()
                    .map(DtrdEntRdSigninBloodPressure::getBloodPressureHighPressure)
                    .filter(Objects::nonNull)
                    .collect(Collectors.averagingInt(ph -> ph));
            patientTargetValue.setPressureHigh(decimalFormat(avgHigh));
            // 低压
            Double avgLow = bloodPressures.stream()
                    .map(DtrdEntRdSigninBloodPressure::getBloodPressureLowVoltage)
                    .filter(Objects::nonNull)
                    .collect(Collectors.averagingInt(pl -> pl));
            patientTargetValue.setPressureLow(decimalFormat(avgLow));
            // 心率
            Double avgHeartRate = bloodPressures.stream()
                    .map(DtrdEntRdSigninBloodPressure::getBloodPressureHeartRate)
                    .filter(Objects::nonNull)
                    .collect(Collectors.averagingInt(hr -> hr));
            patientTargetValue.setHeartRate(decimalFormat(avgHeartRate));
        }
        // 空腹血糖
        LambdaQueryWrapper<DtrdEntRdSigninSugarValue> queryWrapper2 = Wrappers.lambdaQuery(DtrdEntRdSigninSugarValue.class)
                .eq(DtrdEntRdSigninSugarValue::getPatientId, patientId)
                .eq(DtrdEntRdSigninSugarValue::getSugarValueTimeTypeId, Constant.SugarRecordType.BEFOREBREAKFAST.getType());
        if (Objects.equals(type, thisWeek)) {
            queryWrapper2.le(DtrdEntRdSigninSugarValue::getRecordDate, thisWeekDays.get(6))
                    .ge(DtrdEntRdSigninSugarValue::getRecordDate, thisWeekDays.get(0));
        }
        if (Objects.equals(type, lastWeek)) {
            queryWrapper2.le(DtrdEntRdSigninSugarValue::getRecordDate, lastWeekDays.get(6))
                    .ge(DtrdEntRdSigninSugarValue::getRecordDate, lastWeekDays.get(0));
        }
        List<DtrdEntRdSigninSugarValue> sugarLimosisList = sugarRecordService.list(queryWrapper2);
        if (CollectionUtil.isNotEmpty(sugarLimosisList)) {
            Double avgSugarLimosis = sugarLimosisList.stream()
                    .map(DtrdEntRdSigninSugarValue::getSugarValueSugarValue)
                    .filter(Objects::nonNull)
                    .collect(Collectors.averagingDouble(sl -> sl));
            patientTargetValue.setFbg(decimalFormat(avgSugarLimosis));
        }
        // 餐后血糖
        LambdaQueryWrapper<DtrdEntRdSigninSugarValue> queryWrapper3 = Wrappers.lambdaQuery(DtrdEntRdSigninSugarValue.class)
                .eq(DtrdEntRdSigninSugarValue::getPatientId, patientId)
                .in(DtrdEntRdSigninSugarValue::getSugarValueTimeTypeId,
                        Constant.SugarRecordType.AFTERBREAKFAST.getType(),
                        Constant.SugarRecordType.AFTERLUNCH.getType(),
                        Constant.SugarRecordType.AFTERDINNER.getType());
        if (Objects.equals(type, thisWeek)) {
            queryWrapper3.le(DtrdEntRdSigninSugarValue::getRecordDate, thisWeekDays.get(6))
                    .ge(DtrdEntRdSigninSugarValue::getRecordDate, thisWeekDays.get(0));
        }
        if (Objects.equals(type, lastWeek)) {
            queryWrapper3.le(DtrdEntRdSigninSugarValue::getRecordDate, lastWeekDays.get(6))
                    .ge(DtrdEntRdSigninSugarValue::getRecordDate, lastWeekDays.get(0));
        }
        List<DtrdEntRdSigninSugarValue> sugarAfterMealList = sugarRecordService.list(queryWrapper3);
        if (CollectionUtil.isNotEmpty(sugarAfterMealList)) {
            Double avgSugarAfterMeal = sugarAfterMealList.stream()
                    .map(DtrdEntRdSigninSugarValue::getSugarValueSugarValue)
                    .filter(Objects::nonNull)
                    .collect(Collectors.averagingDouble(sam -> sam));
            patientTargetValue.setPbg(decimalFormat(avgSugarAfterMeal));
        }
        // bmi & 体重
        LambdaQueryWrapper<DtrdEntRdSigninHeightWeight> queryWrapper4 = Wrappers.lambdaQuery(DtrdEntRdSigninHeightWeight.class)
                .eq(DtrdEntRdSigninHeightWeight::getPatientId, patientId)
                .orderByDesc(DtrdEntRdSigninHeightWeight::getRecordDate)
                .last("limit 1");
        if (Objects.equals(type, thisWeek)) {
            queryWrapper4.le(DtrdEntRdSigninHeightWeight::getRecordDate, thisWeekDays.get(6))
                    .ge(DtrdEntRdSigninHeightWeight::getRecordDate, thisWeekDays.get(0));
        }
        if (Objects.equals(type, lastWeek)) {
            queryWrapper4.le(DtrdEntRdSigninHeightWeight::getRecordDate, lastWeekDays.get(6))
                    .ge(DtrdEntRdSigninHeightWeight::getRecordDate, lastWeekDays.get(0));
        }
        DtrdEntRdSigninHeightWeight heightWeight = heightWeightRecordService.getOne(queryWrapper4);
        if (heightWeight != null) {
            patientTargetValue = patientTargetValue.setWeightAndBmi(heightWeight);
        }
        // 用药
        LambdaQueryWrapper<DtrdEntRdSigninMedicalRecord> queryWrapper5 = Wrappers.lambdaQuery(DtrdEntRdSigninMedicalRecord.class)
                .eq(DtrdEntRdSigninMedicalRecord::getPatientId, patientId)
                .orderByDesc(DtrdEntRdSigninMedicalRecord::getCreateTime)
                .last("limit 1");
        if (Objects.equals(type, thisWeek)) {
            queryWrapper5.le(DtrdEntRdSigninMedicalRecord::getRecordDate, thisWeekDays.get(6))
                    .ge(DtrdEntRdSigninMedicalRecord::getRecordDate, thisWeekDays.get(0));
        }
        if (Objects.equals(type, lastWeek)) {
            queryWrapper5.le(DtrdEntRdSigninMedicalRecord::getRecordDate, lastWeekDays.get(6))
                    .ge(DtrdEntRdSigninMedicalRecord::getRecordDate, lastWeekDays.get(0));
        }
        DtrdEntRdSigninMedicalRecord medicalRecord = medicalRecordService.getOne(queryWrapper5);
        if (medicalRecord != null) {
            patientTargetValue = patientTargetValue.setDrug(medicalRecord);
        }
        // 腰围
        LambdaQueryWrapper<DtrdEntRdSigninWaistline> queryWrapper6 = Wrappers.lambdaQuery(DtrdEntRdSigninWaistline.class)
                .eq(DtrdEntRdSigninWaistline::getPatientId, patientId);
        if (Objects.equals(type, thisWeek)) {
            queryWrapper6.le(DtrdEntRdSigninWaistline::getRecordDate, thisWeekDays.get(6))
                    .ge(DtrdEntRdSigninWaistline::getRecordDate, thisWeekDays.get(0));
        }
        if (Objects.equals(type, lastWeek)) {
            queryWrapper6.le(DtrdEntRdSigninWaistline::getRecordDate, lastWeekDays.get(6))
                    .ge(DtrdEntRdSigninWaistline::getRecordDate, lastWeekDays.get(0));
        }
        List<DtrdEntRdSigninWaistline> waistlines = waistlineRecordService.list(queryWrapper6);
        if (CollectionUtil.isNotEmpty(waistlines)) {
            Double avgWaist = waistlines.stream()
                    .map(DtrdEntRdSigninWaistline::getWaistlineValue)
                    .filter(Objects::nonNull)
                    .collect(Collectors.averagingDouble(w -> w));
            patientTargetValue.setWaistLine(decimalFormat(avgWaist));
        }
        // 实验室检查的数据，有 血红蛋白(Hb1Ac) 总胆固醇(TC) 高密度脂蛋白(HDL) 低密度脂蛋白(LDL) 等数据
        if (Objects.equals(type, thisWeek)) {
            DtrdEntRdArchiveLaboratory laboratory = laboratoryService.getOne(Wrappers.lambdaQuery(DtrdEntRdArchiveLaboratory.class)
                    .eq(DtrdEntRdArchiveLaboratory::getPatientId, patientId));
            if (laboratory != null) {
                patientTargetValue = patientTargetValue.setLabValue(laboratory);
            }
        }
        return patientTargetValue;
    }

    @Override
    public List<WeekRecordSummary> getWeekSummary(Integer patientId) {
        List<WeekRecordSummary> list = new ArrayList<>(10);
        // 计算本周与上周开始结束日期
        Date today = new Date();
        DateTime weekDateTime = DateUtil.beginOfWeek(today);
        DateTime weekEndDate = DateUtil.endOfWeek(today);
        String startOfWeek = DateUtils.formatDate(weekDateTime);
        String endOfWeek = DateUtils.formatDate(weekEndDate);
        String lastStartOfWeek = DateUtils.dateAdd(-7, startOfWeek, DateUtils.date_sdf.get().toPattern(), Calendar.DATE);
        String lastEndOfWeek = DateUtils.dateAdd(-1, startOfWeek, DateUtils.date_sdf.get().toPattern(), Calendar.DATE);
        TargetAndDetailInfo target = targetService.getLastTargetAndDetailsInfo(patientId);
        if (target == null) {
            target = new TargetAndDetailInfo();
        }
        // 本周BMI
        Integer bmiAvgValue = heightWeightRecordService.getAvgBmi(patientId, startOfWeek, endOfWeek);
        // 上周BMI
        Integer lastBmiAvgValue = heightWeightRecordService.getAvgBmi(patientId, lastStartOfWeek, lastEndOfWeek);
        list.add(initSummary("BMI", bmiAvgValue, lastBmiAvgValue, null, target.getBmi()));
//        //身高体重
//        Float avgWeight = heightWeightRecordService.getAvgWeight(patientId, startOfWeek, endOfWeek);
//        Float lastAvgWeight = heightWeightRecordService.getAvgWeight(patientId, lastStartOfWeek, lastEndOfWeek);
//        list.add(initSummary("体重", avgWeight), lastAvgWeight), null, PLACEHOLDER));
        // 计算本周腰围
        Integer waistAvgValue = waistlineRecordService.getAvgWaist(patientId, startOfWeek, endOfWeek);
        // 计算上周
        Integer lastWaistAvgValue = waistlineRecordService.getAvgWaist(patientId, lastStartOfWeek, lastEndOfWeek);
        list.add(initSummary("腰围", waistAvgValue, lastWaistAvgValue, null, target.getWaist()));

        // 计算本周糖化
//        Integer hba1cAvgValue = bloodPressureRecordService.getAvgBloodHeartrate(patientId, startOfWeek, endOfWeek);
//        // 计算上周
//        Integer lastHba1cAvgValue = bloodPressureRecordService.getAvgBloodHeartrate(patientId, lastStartOfWeek, lastEndOfWeek);
//        list.add(initSummary("糖化血红蛋白", hba1cAvgValue), lastHba1cAvgValue), null, target.getHbA1c())));

        String beforeBreakfastType = "(" + Constant.SugarRecordType.BEFOREBREAKFAST.getType() + ")";
        // 计算本周空腹平均血糖
        Float beforeBreakfastAvgValue = sugarRecordService.getAvgSugarRecord(patientId, startOfWeek, endOfWeek, beforeBreakfastType);
        // 计算上周空腹血糖
        Float lastBeforeBreakfastAvgValue = sugarRecordService.getAvgSugarRecord(patientId, lastStartOfWeek, lastEndOfWeek, beforeBreakfastType);
        // 当前空腹控制目标
        list.add(initSummary("空腹血糖", beforeBreakfastAvgValue, lastBeforeBreakfastAvgValue, null, target.getFbg()));

        // 计算餐后血糖
        String afterType = "(" + Constant.SugarRecordType.AFTERBREAKFAST.getType() + "," + Constant.SugarRecordType.AFTERLUNCH.getType() + "," + Constant.SugarRecordType.AFTERDINNER.getType() + ")";
        // 计算本周餐后
        Float afterAvgValue = sugarRecordService.getAvgSugarRecord(patientId, startOfWeek, endOfWeek, afterType);
        // 计算上周餐后
        Float lastAfterAvgValue = sugarRecordService.getAvgSugarRecord(patientId, lastStartOfWeek, lastEndOfWeek, afterType);
        // 当前餐后控制目标
        list.add(initSummary("餐后血糖", afterAvgValue, lastAfterAvgValue, null, target.getPbg()));

        // 计算血压平均值
        // 本周高/低压
        Integer bpHighAvgValue = bloodPressureRecordService.getAvgBloodHighPressure(patientId, startOfWeek, endOfWeek);
        //上周高/低压
        Integer lastBpHighAvgValue = bloodPressureRecordService.getAvgBloodHighPressure(patientId, lastStartOfWeek, lastEndOfWeek);
        // 当前血压控制目标
        list.add(initSummary("收缩压", bpHighAvgValue, lastBpHighAvgValue, null, target.getPressureHigh()));

        Integer bpLowAvgValue = bloodPressureRecordService.getAvgBloodLowPressure(patientId, startOfWeek, endOfWeek);
        Integer lastBpLowAvgValue = bloodPressureRecordService.getAvgBloodLowPressure(patientId, lastStartOfWeek, lastEndOfWeek);
        list.add(initSummary("舒张压", bpLowAvgValue, lastBpLowAvgValue, null, target.getPressureLow()));

        // 计算本周心率
        Integer heartLowAvgValue = bloodPressureRecordService.getAvgBloodHeartrate(patientId, startOfWeek, endOfWeek);
        // 计算上周
        Integer lastHeartLowAvgValue = bloodPressureRecordService.getAvgBloodHeartrate(patientId, lastStartOfWeek, lastEndOfWeek);
        list.add(initSummary("心率", heartLowAvgValue, lastHeartLowAvgValue, null, target.getHeartRate()));

        // 计算本周总胆固醇

        // 计算上周

//        list.add(initSummary("总胆固醇", "", "", null, target.getBmi()));
        // 计算本周甘油三酯

        // 计算上周

//        list.add(initSummary("甘油三酯", "", "", null, target.getBmi()));
        // 计算本周低密度脂蛋白

        // 计算上周

//        list.add(initSummary("低密度脂蛋白", "", "", null, target.getBmi()));
        // 计算本周高密度脂蛋白

        // 计算上周

//        list.add(initSummary("高密度脂蛋白", "", "", null, target.getBmi()));
        return list;
    }

    @Override
    public TargetTable getPatientTargetTable(Integer patientId) {
        List<Integer> projectTypes = baseMapper.selectTargetTypes(patientId);
        if (CollectionUtil.isEmpty(projectTypes)) {
            return null;
        }
        TargetTable table = new TargetTable();
        //region 表头
        List<String> tableHeader = new ArrayList<>(16);
        tableHeader.add("打卡项");
        tableHeader.add("达标率");
        projectTypes.forEach(p -> tableHeader.add(TargetProject.valueOf(p).getName()));
        table.setTableth(tableHeader);
        //endregion
        //region 表数据
        Map<Integer, Integer> idToRate = getTargetIdToReachStandardRate(patientId, null, null);
        List<List<String>> tableData = new ArrayList<>(16);
        List<DtrdEntRdSigninTargetDetail> details = baseMapper.selectTargetDetails(patientId, null, null);
        Map<Integer, List<DtrdEntRdSigninTargetDetail>> map = details
                .stream()
                .collect(Collectors.groupingBy(DtrdEntRdSigninTargetDetail::getTargetId,LinkedHashMap::new, Collectors.toList()));
        int count = 0;
        for (Map.Entry<Integer, List<DtrdEntRdSigninTargetDetail>> entry : map.entrySet()) {
            List<DtrdEntRdSigninTargetDetail> value = entry.getValue();
            // 加上初始值
            if (count == 0) {
                List<String> initLine = new ArrayList<>(16);
                initLine.add("初始值");
                initLine.add("/");
                setTableData(projectTypes, initLine, value, true);
                tableData.add(initLine);
            }
            List<String> tableLine = new ArrayList<>(16);
            tableLine.add(NumberUtil.getWeekStr(++count));
            Integer key = entry.getKey();
            tableLine.add(idToRate.get(key) + "%");
            setTableData(projectTypes, tableLine, value, false);
            tableData.add(tableLine);
        }
        table.setList(tableData);
        //endregion
        return table;
    }

    @Override
    public TargetTable getPatientTargetTableV2(Integer patientId) {
        // 获取用户的服务包的结束时间(选择只有已过期已退出的或者还是在服务的结束时间最末的)
        DtrdRlPackagePatient packagePatient = getEndTimePackage(patientId);
        if(packagePatient == null){
            return null;
        }
        // 添加时间范围
        Date startTime = packagePatient.getStartTime();
        Date endTime = packagePatient.getEndTime();
        Date nowTime = DateUtils.getDateYMD();
        // 选择最早结束的时间作为结束时间
        endTime = DateUtils.compareYMD(endTime, nowTime)?nowTime:endTime;
        List<List<String>> dateStringArray = DateUtils.getWeekStartEndStringArray(startTime, endTime);
        List<List<Date>> dateArray = DateUtils.getWeekStartEndDateArray(startTime, endTime);
        if(dateArray == null || dateStringArray == null){
            return null;
        }
        // region 获取每周的打卡目标值
        List<Map<Integer, DtrdEntRdSigninTargetDetail>> weekList = getWeekSigninTargetDetail(patientId, dateArray);
        // endregion 获取每周的打卡目标值
        // 纵坐标长度-1 = weekSize,需要添加一个初始值
        int weekSize = dateArray.size();
        // 创建表格对象
        TargetTable table = new TargetTable();
        // 表头
        List<String> headers = new ArrayList<>();
        // region初始化前两列的数据
        headers.add("打卡项");
        headers.add("达标率");
        // region 创建内容数据并进行初始化
        int rowLength = weekSize + 1;
        List<List<String>> content = new ArrayList<>(rowLength);
        for(int i = 0; i< rowLength; i++){
            List<String> temp = new ArrayList<>();
            content.add(temp);
        }
        content.get(0).add("初始值");
        content.get(0).add("-");
        // endregion 创建内容数据并进行初始化
        for (int i = 1; i < rowLength; i++) {
            int key = i-1;
            content.get(i).add("第"+ i + "周");
            // region更新达标率
            List<Date> date = dateArray.get(key);
            Integer weekReachRate = handlerReachRate(uplowRecordService.getPeriodControllerTargetsReachRate(
                    patientId,date.get(0),date.get(1),weekList.get(key)));
            content.get(i).add(weekReachRate + "%");
            // endregion 更新达标率
        }
        // endregion 初始化前两列的数据
        for(Constant.TargetProject targetProject:Constant.TargetProject.values()){
            boolean isNotHave = true;
            // region 判断是否有这一项打卡计划，有则进行计算，没有直接跳过
            for(Map<Integer, DtrdEntRdSigninTargetDetail> item: weekList){
                if(item.containsKey(targetProject.getType())){
                    isNotHave = false;
                    break;
                }
            }
            if(isNotHave) {
                continue;
            }
            // endregion 判断是否有这一项打卡计划，有则进行计算，没有直接跳过
            // 添加该项的表头
            headers.add(targetProject.getName());
            // region 第14项用药情况需要单独处理
            if(targetProject.equals(TargetProject.DRUG)){
                content.get(0).add("/");
                for (int i = 0; i < weekSize; i++) {
                    Map<Integer, DtrdEntRdSigninTargetDetail> weekSigninTargetMap = weekList.get(i);
                    DtrdEntRdSigninTargetDetail temp = weekSigninTargetMap.get(targetProject.getType());
                    String tempString = temp == null||temp.getRemark()==null?"-":temp.getRemark();
                    content.get(i+1).add(tempString);
                }
                continue;
            }
            // endregion 第14项用药情况需要单独处理
            // region 获取初始值
            Float startValue = getFirstTargetValue(patientId, targetProject);
            content.get(0).add(startValue == null ? "-":startValue.toString());
            // endregion 获取初始值
            // region 补充每周的打卡细节
            for(int i = 0; i<weekSize; i++){
                int key = i + 1;
                Map<Integer, DtrdEntRdSigninTargetDetail> weekSigninTargetMap = weekList.get(i);
                List<String> dateList = dateStringArray.get(i);
                // region 获取目标打卡值
                DtrdEntRdSigninTargetDetail temp = weekSigninTargetMap.get(targetProject.getType());
                Float avgValue = getAvgTargetValue(patientId, dateList.get(0), dateList.get(1), targetProject);
                String tempString = temp == null||temp.getValue()==null?"-":temp.getValue().toString();
                String avgValueString = avgValue == null? "-":avgValue.toString();
                content.get(key).add(avgValueString + "/" + tempString);
                // endregion 获取目标打卡值
            }
            // endregion 补充每周的打卡细节
        }
        table.setTableth(headers);
        table.setList(content);
        return table;
    }

    private void setTableData(List<Integer> projectTypes, List<String> tableLine, List<DtrdEntRdSigninTargetDetail> targets, boolean init) {
        for (Integer projectType : projectTypes) {
            Optional<DtrdEntRdSigninTargetDetail> optional = targets.stream()
                    .filter(v -> v.getProjectType().equals(projectType)).findAny();
            String data = optional
                .map(d -> {
                    try {
                        if (init) {
                            return d.getTargetHigh() + "";
                        }else {
                            return d.getProjectType().equals(TargetProject.DRUG.getType()) ? d.getRemark() : d.getValue() + "/" + d.getTargetLow();
                        }
                    }catch (Exception e) {
                        log.error("控制目标记录值错误, 记录id:{}, value: {}, low: {}, high:{}", d.getDataId(), d.getValue(), d.getTargetLow(), d.getTargetHigh());
                        return "";
                    }
                })
                .orElse("");
            tableLine.add(data);
        }
    }

    private WeekRecordSummary initSummary(String name, Object thisWeekValue, Object lastWeekValue, String nameSpec, Object target) {
        WeekRecordSummary summary = new WeekRecordSummary();
        // 赋值
        summary.setName(name);
        summary.setNameSec(nameSpec);
        summary.setThisWeek(wrapperValue(thisWeekValue));
        summary.setLastWeek(wrapperValue(lastWeekValue));
        summary.setWeekTarget(wrapperValue(target));
        // 处理state
        // 本周/上周比较
        if (!Objects.equals(summary.getLastWeek(), PLACEHOLDER) && !Objects.equals(summary.getThisWeek(), PLACEHOLDER)) {
            float lastWeek = Float.parseFloat(summary.getLastWeek());
            float thisWeek = Float.parseFloat(summary.getThisWeek());
            if (thisWeek < lastWeek) {
                summary.setThisWeekState(Constant.PatientDataCompare.DECLINE.getType());
            } else if (thisWeek > lastWeek) {
                summary.setThisWeekState(Constant.PatientDataCompare.RISE.getType());
            } else {
                summary.setThisWeekState(Constant.PatientDataCompare.EQUAL.getType());
            }
        }
        // 达标状态
        if (!Objects.equals(summary.getThisWeek(), PLACEHOLDER) && !Objects.equals(summary.getWeekTarget(), PLACEHOLDER)) {
            float thisWeek = Float.parseFloat(summary.getThisWeek());
            float targetVal = Float.parseFloat(summary.getWeekTarget());
            if (thisWeek <= targetVal) {
                summary.setWeekTargetState(Constant.ReachStandardStatus.REACH.getType());
            } else {
                summary.setWeekTargetState(Constant.ReachStandardStatus.NO_REACH.getType());
            }
        }
        return summary;
    }


    private String wrapperValue(Object value) {
        return value == null ? PLACEHOLDER : String.valueOf(value);
    }

    private static float decimalFormat(Double d) {
        float floatValue = d.floatValue();
        DecimalFormat decimalFormat = new DecimalFormat("0.0");
        String s = decimalFormat.format(floatValue);
        return Float.parseFloat(s);
    }
}




